﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;
using WsProtocol.IEC62056.DataTypeClass;

namespace WsProtocol.IEC62056
{
    /// <summary>
    /// // hxh 2018-5 62056
    /// </summary>
    [Serializable]
    public class ElementData //: ICloneable
    {
        private object m_tag = null;
        private string m_CAD;  //保存某些需要的CAD        
        private bool m_visible = true;  //用于界面是否显示
        private string m_ValueName;　//数据名称
        private string m_InputValue;  //界面输入的原始值
        private string m_SetValue;　　//界面输入值标准化处理后的实际设置值

        private string m_FrameValue;　//返回命令帧中的原始数据

        private string m_ReadValue;　//解析完后最终数据

        private string m_DataType;　//数据类型
        private string m_DataLen;　//长度
        private string m_Scaler;　//换算        
        private string m_Units;　//单位
        private string m_ShowFormat;  //显示格式
        private string m_Display;  //分解描述
        private string m_DataTypeDIY;
        private string m_tmpOption;  //界面选择 例如 choice
  
        private List<ElementData> m_eleNodeList;       
        #region Public Properties
        public object Tag = null;
        //{
        //    get
        //    {
        //        return m_tag;
        //    }
        //    set
        //    {
        //        m_tag = value;
        //    }
        //}
        public string CAD
        {
            get
            {
                return m_CAD;
            }
            set
            {
                m_CAD = value;
            }
        }
        
        public bool visible
        {
            get
            {
                return m_visible;
            }
            set
            {
                m_visible = value;
            }
        }

        public string ValueName
        {
            get
            {
                return m_ValueName;
            }
            set
            {
                m_ValueName = value;
            }
        }

        public string InputValue
        {
            get
            {
                return m_InputValue;
            }
            set
            {
                m_InputValue = value;
            }
        }
        public string SetValue
        {
            get
            {
                return m_SetValue;
            }
            set
            {
                m_SetValue = value;
            }
        }
        public string FrameValue
        {
            get
            {
                return m_FrameValue;
            }
            set
            {
                m_FrameValue = value;
            }
        }
        public string ReadValue
        {
            get
            {
                return  m_ReadValue;
            }
            set
            {
                m_ReadValue = value;
            }
        }
        public string DataType
        {
            get
            {
                return m_DataType;
            }
            set
            {
                m_DataType = value;
            }
        }
        public string DataLen
        {
            get
            {
                return m_DataLen;
            }
            set
            {
                m_DataLen = value;
            }
        }
        public string Scaler
        {
            get
            {
                return m_Scaler;
            }
            set
            {
                m_Scaler = value;
            }
        }
        //public string ShowScaler
        //{
        //    get
        //    {
        //        return m_ShowScaler;
        //    }
        //    set
        //    {
        //        m_ShowScaler = value;
        //    }
        //}
        public string Units
        {
            get
            {
                return m_Units;
            }
            set
            {
                m_Units = value;
            }
        }
       
        public List<ElementData> eleNodeList
        {
            get
            {
                return m_eleNodeList;
            }
            set
            {
                m_eleNodeList = value;
            }
        }
        //public List<ElementData> ParAttrLst
        //{
        //    get
        //    {
        //        return m_ParAttrLst;
        //    }
        //    set
        //    {
        //        m_ParAttrLst = value;
        //    }
        //}
        public string ShowFormat  //显示格式
        {
            get
            {
                return m_ShowFormat;
            }
            set
            {
                m_ShowFormat = value;
            }
        }
        public string Display  //分解描述
        {
            get
            {
                return m_Display;
            }
            set
            {
                m_Display = value;
            }
        }

        public string DataTypeDIY
        {
            get
            {
                return m_DataTypeDIY;
            }
            set
            {
                m_DataTypeDIY = value;
            }
        }

         //界面选择 例如 choice
        public string tmpOption
        {
            get
            {
                return m_tmpOption;
            }
            set
            {
                m_tmpOption = value;
            }
        }

        public int CompareResult { get; set; } //比对结果 0未比对，1比对正确 －1 比对错误
        #endregion

        public ElementData()
        {
            m_eleNodeList = new List<ElementData>();
           
        }

        public ElementData(object NodeData, object childNodelist, object tag)
        {
            m_tag = tag;

            if (childNodelist == null)
                m_eleNodeList = new List<ElementData>();
            else
                m_eleNodeList = (List<ElementData>)childNodelist;

           
            try
            {
                object[] DataArray = (object[])NodeData;
                m_ValueName = DataArray[0].ToString();
                m_SetValue = DataArray[1].ToString();
                m_DataType = DataArray[2].ToString();
                m_DataLen = DataArray[3].ToString();
                m_Scaler = DataArray[4].ToString();
                m_Units = DataArray[5].ToString();

            }
            catch (Exception ex)
            {
            }
        }

        //public object Clone()
        //{
        //    return this.MemberwiseClone();
        //}

        //public object DeepClone()
        //{
        //    MemoryStream ms = new MemoryStream();
        //    BinaryFormatter bf = new BinaryFormatter();
        //    bf.Serialize(ms, this);
        //    ms.Position = 0;
        //    return bf.Deserialize(ms) as ElementData;
        //}

        public ElementData DeepClone()
        {
            //新建一个
            ElementData newele = new ElementData();

            //复制属性
            PropertyInfo[] fromFields = typeof(ElementData).GetProperties();
            SetProperties(fromFields, this, newele);

            //复制包含的属性列表
            newele.eleNodeList = new List<ElementData>();
            if (this.eleNodeList != null)
                for (int i = 0; i < this.eleNodeList.Count; i++)
                {
                    ElementData ason = this.eleNodeList[i].DeepClone();
                    newele.eleNodeList.Add(ason);
                }

            newele.Tag = this.Tag;

            ////复制附加属性列表
            //newele.ParAttrLst = new List<ElementData>();
            //if (this.ParAttrLst != null)
            //    for (int i = 0; i < this.ParAttrLst.Count; i++)
            //    {
            //        ElementData sonObj = this.ParAttrLst[i].DeepClone();
            //        newele.ParAttrLst.Add(sonObj);
            //    }
            return newele;
        }

        /// <summary>
        /// 复制类属性 3参数
        /// </summary>
        /// <param name="fromFields"></param>
        /// <param name="fromRecord"></param>
        /// <param name="toRecord"></param>
        private void SetProperties(PropertyInfo[] fromFields,
                                         object fromRecord,
                                         object toRecord)
        {
            PropertyInfo fromField = null;

            try
            {

                if (fromFields == null)
                {
                    return;
                }

                for (int f = 0; f < fromFields.Length; f++)
                {

                    fromField = (PropertyInfo)fromFields[f];

                    fromField.SetValue(toRecord,
                                       fromField.GetValue(fromRecord, null),
                                       null);
                }

            }
            catch (Exception)
            {
                throw;
            }
        }


        public int AddNode(ElementData mNode)
        {
            if (m_eleNodeList == null)
                m_eleNodeList = new List<ElementData>();
            m_eleNodeList.Add(mNode);
            return 1;
        }

      
        /// <summary>
        /// 比较设置值和抄读值是否一致，只比对子节点，父节点的值不比对
        /// </summary>
        /// <returns>1:比对正确  0:不用比对  -1:比对错误</returns>
        public int CompareValue()
        {
            int rs = 0;
            string setvalue = string.IsNullOrEmpty(m_SetValue) ? m_InputValue : m_SetValue;  //如果setvalue为空则赋inputvalue比较,底层对于esam参数抄读时人为把setvalue赋为了NULL
        
            if (string.IsNullOrEmpty(setvalue))
                setvalue = "0";

            if (string.IsNullOrEmpty(m_ReadValue))
                m_ReadValue = "0";
            setvalue = setvalue.Replace("\r", "");
            m_ReadValue = m_ReadValue.Replace("\r", "");
            if (setvalue == m_ReadValue)
                return 1;
            if (eleNodeList.Count > 0)
                return rs;
            try
            {
                string sdtype = string.IsNullOrEmpty(m_DataTypeDIY) ? m_DataType : m_DataTypeDIY;
                if (string.IsNullOrEmpty(sdtype)) return rs;
                enumData dtype = (enumData)Enum.Parse(typeof(enumData), sdtype);
              
                switch (dtype)
                {
                    case enumData.date:
                        string Rvalue = m_ReadValue.Replace("-", "").Replace(":", "").Replace(" ", "").Replace("FF", "00"); //把时间里面的其他字符去掉
                        setvalue = setvalue.Replace("-", "").Replace(":", "").Replace(" ", "").Replace("FF", "00");
                        rs = Rvalue == setvalue ? 1 : -1;
                        break;
                    case enumData.date_time:    //比较日期时间，相差3秒内                      
                        string[] RvalueLst = m_ReadValue.ToUpper().Split(new char[] { '-', ':', ' ' });
                        string[] SvalueLst = m_InputValue.ToUpper().Split(new char[] { '-', ':', ' ' });
                        for (int i = 0; i < RvalueLst.Length; i++) {
                            if (rs < 0) break;
                            switch (i) {
                                case 0://年
                                    if ((RvalueLst[i].Contains("FFFF") || SvalueLst[i].Contains("FFFF")))                                   
                                        rs = 1;                                   
                                    else
                                        rs = RvalueLst[i] == SvalueLst[i] ? 1 : -1;
                                    break;
                                case 6: //秒的比较
                                    rs = Convert.ToInt64(RvalueLst[i]) - Convert.ToInt64(SvalueLst[i]) <= 3 ? 1 : -1;
                                    break;
                                case 7: //毫秒
                                    rs = 1; break;
                                case 8: //8000
                                    rs = RvalueLst[i] == SvalueLst[i] ? 1 : -1; break;
                                default:
                                    if ((RvalueLst[i].Contains("FF") || SvalueLst[i].Contains("FF")))
                                    {
                                        rs = 1;
                                    }
                                    else
                                        rs = RvalueLst[i] == SvalueLst[i] ? 1 : -1;break;
                            }                         
                        }                       
                       // string Rdt = m_ReadValue.Replace("-", "").Replace(":", "").Replace(" ", "").Substring(14, 2); //只把前面的年到秒的数据取出
                       // string Sdt = setvalue.Substring(14, 2);
                                               
                       // Rvalue = m_ReadValue.Replace("-", "").Replace(":", "").Replace(" ", "").Remove(14); //,2
                       // setvalue = setvalue.Remove(14); //, 2
                       // //时间日期比对，考虑到通配符情况比对，把秒字节单独取出。剩下的进行字符串比对。秒字节进行小于3秒内的比对
                       // //if (Rvalue != setvalue)
                       // //{
                       // //    rs = -1;
                       // //}
                       // //else
                       // //{
                       //     rs = Convert.ToInt64(Rdt) - Convert.ToInt64(Sdt) <= 3 ? 1 : -1;
                       //// }
                        break;
                  //  case enumData.date:
                    case enumData.time:
                        //i = 0;
                        //while (i < m_ReadValue.Length && m_ReadValue.Contains("FF"))
                        //{  //hxh 如果时间里有FF，用设置数据同位置的数替换
                        //    int pp = m_ReadValue.IndexOf("FF");
                        //    if (setvalue.Substring(pp, 2) != "FF")
                        //       m_ReadValue = m_ReadValue.Replace("FF", setvalue.Substring(pp, 2));
                        //    i += 2;
                        //}
                        Rvalue = m_ReadValue.Replace(":", "").Replace(" ", "").Replace("FF", "00"); //把时间里面的其他字符去掉
                        setvalue = setvalue.Replace(":", "").Replace(" ", "").Replace("FF", "00");
                        if (setvalue != "0" && Rvalue.Length != setvalue.Length)
                            Rvalue = Rvalue.Trim('\0').Substring(0, setvalue.Length);
                        rs = Rvalue == setvalue ? 1 : -1;
                        
                        break;
                    case enumData.Enum:
                        rs = Convert.ToDouble(setvalue) == Convert.ToDouble(m_ReadValue) ? 1 : -1;
                        break;
                    case enumData.double_long:
                    case enumData.double_long_unsigned:                    
                    case enumData.float32:
                    case enumData.float64:
                    case enumData.Long:                    
                    case enumData.integer:
                    case enumData.long64:
                    case enumData.long64_unsigned:
                    case enumData.unsigned:
                    case enumData.long_unsigned:
                        if (string.IsNullOrEmpty(setvalue))
                            rs = Convert.ToDouble(m_ReadValue) == 0 ? 1 : -1;
                        else
                            rs = Convert.ToDouble(setvalue) == Convert.ToDouble(m_ReadValue) ? 1 : -1;
                        break;
                    case enumData.visible_string:
                        setvalue = string.IsNullOrEmpty(setvalue) ? "NULL" : setvalue;
                        rs = setvalue == m_ReadValue.Trim('\0') ? 1 : -1;
                        break;               
                   
                    default:
                        rs = setvalue == m_ReadValue.Trim('\0') ? 1 : -1;
                        break;

                }
            }
            catch
            {
                rs = -1;
            }
            CompareResult = rs;
            return rs;
        }

        public int CompareValueList() {
            
            if (this.eleNodeList.Count == 0)            
                return this.CompareValue();            
            
            for (int i = 0; i < this.eleNodeList.Count; i++) {
                this.eleNodeList[i].CompareValueList();
            }

            this.CompareResult = 1;
            for (int j = 0; j < this.eleNodeList.Count; j++)
            {
                if(this.eleNodeList[j].CompareResult == -1){
                    this.CompareResult = -1; //更新父节点的比对结果
                    break;
                }
            }
            return this.CompareResult;
        }

        public void UpdateScalerUnit(string scaler, string unit) {
            if (m_Scaler != scaler ){
                m_Scaler = scaler;
                string errinfo = string.Empty;
                enumData dtype = (enumData)Enum.Parse(typeof(enumData), this.m_DataType);
                Data.AnalizeDtypeData(ref this.m_FrameValue, this, dtype, 1, ref errinfo);
            }
            if( m_Units != unit) 
                m_Units = unit;
            
        }


        public void ClearEleParams(bool ClearCAD) {
            this.ReadValue = this.FrameValue = this.SetValue = this.InputValue = string.Empty;
            if(ClearCAD)
                this.CAD = string.Empty;
            for (int i = 0; i < m_eleNodeList.Count; i++)
                m_eleNodeList[i].ClearEleParams(ClearCAD);
        }

    }

}

